pub mod codec;

use std::{future::Future, net::SocketAddr};

use self::codec::ChannelEndCodec;
use tokio::{
    io::{AsyncRead, AsyncWrite},
    net::{TcpListener, TcpStream},
};
use tokio_util::codec::Framed;

pub(crate) type RawChannelEnd<C, SD, I, O> = Framed<C, ChannelEndCodec<I, O, SD>>;

pub trait ConnectionSource {
    type Conn: AsyncRead + AsyncWrite;
    type OtherEndInfo;
    type Err: Into<std::io::Error>;

    fn get_one(
        &self,
    ) -> impl Future<Output = Result<(Self::Conn, Self::OtherEndInfo), Self::Err>> + Send;
}

pub struct TcpConnectionStream(TcpListener);

impl TcpConnectionStream {
    pub async fn new(addr: SocketAddr) -> std::io::Result<Self> {
        TcpListener::bind(addr).await.map(Self)
    }
}
impl ConnectionSource for TcpConnectionStream {
    type Conn = TcpStream;
    type OtherEndInfo = SocketAddr;
    type Err = std::io::Error;

    fn get_one(
        &self,
    ) -> impl Future<Output = Result<(Self::Conn, Self::OtherEndInfo), Self::Err>> + Send {
        self.0.accept()
    }
}
